using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;

using NUnit.Framework;

using PerfectStorm.CodeGenLibrary;
using System.Text;

namespace PerfectStorm.CodeGenTest
{
    
    [TestFixture]
    public class TransformEngineTest :  ITransformOutput, ILogger
    {
        private string _target = null;
        private MemoryStream _prevOutput = null;
        private MemoryStream _output = null;
        private TransformEngine _engine;
        private List<ITransformFilter> _filters = null;
        private DictionaryConfiguration _config = null;
        private StringBuilder _log = null;

        [SetUp]
        public void Setup()
        {
            _log = new StringBuilder();
            _config = new DictionaryConfiguration();
            _config.Add("variables", 
                       @"<variables>
                         <variable name=""CodeGen.Tool"">This was generated by PerfectStorm.CodeGen.</variable>
                         </variables>");
            _target = null;
            _prevOutput = null;
            _output = null;

            _filters = new List<ITransformFilter>();
            _filters.Add(new SupressUnicodePrefixFilter());

            TransformContext context = new TransformContext(_config);
            Hashtable extensions = new Hashtable();
            extensions.Add(XsltExtension.EXTENSION_URN, new XsltExtension(context));
            _engine = new TransformEngine(extensions,
                context, _config, this, this, _filters);
        }

        [TearDown]
        public void Teardown()
        {
            _config.Clear();
            _target = null;
            if (_prevOutput != null) _prevOutput.Close();
            _prevOutput = null;
            if (_output != null) _output.Close();
            _output = null;
            _engine = null;
        }
        
        [Test]
        public void FirstTransform()
        { 
            const string targetName = "FirstTransformCreateBatch.bat";
            _engine.ExecuteTransform("TransformEngineTestFirstTransformModel.CodeGen",
                "TransformEngineTestFirstTransformCreateBatch.xslt",
                targetName, 
                null);
            Assert.AreEqual(targetName, _target, "Output name does not match");
            using (FileStream fs = new FileStream(targetName, FileMode.Open))
            {
                TransformTestHelper.StreamCompare(fs, _output, "");
            }
        }

        /// <summary>
        /// This test demonstrates that it is the filter that is removing the three 
        /// characters.
        /// </summary>
        [Test]
        public void FirstTransformClearFilters()
        {
            _filters.Clear();
            const string targetName = "FirstTransformCreateBatch.bat";
            _engine.ExecuteTransform("TransformEngineTestFirstTransformModel.CodeGen",
                "TransformEngineTestFirstTransformCreateBatch.xslt",
                targetName,
                null);
            Assert.AreEqual(targetName, _target, "Output name does not match");
            using (FileStream fs = new FileStream(targetName, FileMode.Open))
            {
                Assert.AreEqual(fs.Length + 3, _output.Length, "Removing filter adds three characters");
            }
        }

        [Test]
        public void FirstTransformMultipleFilters()
        {
            _filters.Add(new SupressUnicodePrefixFilter());
            const string targetName = "FirstTransformCreateBatch.bat";
            _engine.ExecuteTransform("TransformEngineTestFirstTransformModel.CodeGen",
                "TransformEngineTestFirstTransformCreateBatch.xslt",
                targetName,
                null);
            Assert.AreEqual(targetName, _target, "Output name does not match");
            using (FileStream fs = new FileStream(targetName, FileMode.Open))
            {
                TransformTestHelper.StreamCompare(fs, _output, "");
            }
        }

        [Test]
        public void FirstTransformAddLoggingFilter()
        {
            _filters.Add(new LoggingFilter(this));
            const string targetName = "FirstTransformCreateBatch.bat";
            _engine.ExecuteTransform("TransformEngineTestFirstTransformModel.CodeGen",
                "TransformEngineTestFirstTransformCreateBatch.xslt",
                targetName,
                null);
            Assert.AreEqual(targetName, _target, "Output name does not match");
            using (FileStream fs = new FileStream(targetName, FileMode.Open))
            {
                TransformTestHelper.StreamCompare(fs, _output, "");
            }
            Assert.AreEqual("LoggingFilter: BeforeTransform called\r\nLoggingFilter: AfterTransform called\r\n", 
                _log.ToString());            
        }

        #region ITransformOutput Members

        public void WriteOutput(string target, MemoryStream prevOutput, MemoryStream output)
        {
            _target = target;
            _prevOutput = prevOutput;
            _output = output;
        }

        #endregion

        #region ILogger Members

        public void Log(string message)
        {
            _log.AppendLine(message);
        }

        #endregion
    }
}
